﻿//  Copyright (c) 2011 Ray Liang (http://www.dotnetage.com)
//  Licensed MIT: http://www.opensource.org/licenses/mit-license.php

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Security;
using System.Globalization;
using System.Web.Mvc;
using System.Web.Script.Serialization;

namespace DNA.Mvc.Publishing
{
    public class ArticleWrapper : Article
    {
        private Article innerArticle;
        private GlobalizationContent _content = null;

        public ArticleWrapper(Article article)
        {
            innerArticle = article;
        }

        [ScriptIgnore]
        public Article Article { get { return innerArticle; } }

        #region Article overrides

        public override bool AllowComments
        {
            get
            {
                return innerArticle.AllowComments;
            }
            set
            {
                innerArticle.AllowComments = value;
            }
        }

        public override bool AllowPingback
        {
            get
            {
                return innerArticle.AllowPingback;
            }
            set
            {
                innerArticle.AllowPingback = value;
            }
        }

        public override string Body
        {
            get
            {
                return innerArticle.Body;
            }
            set
            {
                innerArticle.Body = value;
            }
        }

        public override string Categories
        {
            get
            {
                return innerArticle.Categories;
            }
            set
            {
                innerArticle.Categories = value;
            }
        }

        [ScriptIgnore]
        public override Category Category
        {
            get
            {
                return innerArticle.Category;
            }
            set
            {
                innerArticle.Category = value;
            }
        }

        public override int CategoryID
        {
            get
            {
                return innerArticle.CategoryID;
            }
            set
            {
                innerArticle.CategoryID = value;
            }
        }

        [ScriptIgnore]
        public override ICollection<Comment> Comments
        {
            get
            {
                return innerArticle.Comments;
            }
            set
            {
                innerArticle.Comments = value;
            }
        }

        public override int ContentFormat
        {
            get
            {
                return innerArticle.ContentFormat;
            }
            set
            {
                innerArticle.ContentFormat = value;
            }
        }

        public override int ID
        {
            get
            {
                return innerArticle.ID;
            }
            set
            {
                innerArticle.ID = value;
            }
        }

        public override bool IsPrivate
        {
            get
            {
                return innerArticle.IsPrivate;
            }
            set
            {
                innerArticle.IsPrivate = value;
            }
        }

        public override string ImageUrl
        {
            get
            {
                return innerArticle.ImageUrl;
            }
            set
            {
                innerArticle.ImageUrl = value;
            }
        }

        public override bool IsAppoved
        {
            get
            {
                return innerArticle.IsAppoved;
            }
            set
            {
                innerArticle.IsAppoved = value;
            }
        }

        public override bool IsPublished
        {
            get
            {
                return innerArticle.IsPublished;
            }
            set
            {
                innerArticle.IsPublished = value;
            }
        }

        public override string Language
        {
            get
            {
                return innerArticle.Language;
            }
            set
            {
                innerArticle.Language = value;
            }
        }

        public override DateTime LastModified
        {
            get
            {
                return innerArticle.LastModified;
            }
            set
            {
                innerArticle.LastModified = value;
            }
        }

        public override int ParentID
        {
            get
            {
                return innerArticle.ParentID;
            }
            set
            {
                innerArticle.ParentID = value;
            }
        }

        [ScriptIgnore]
        public override string Password
        {
            get
            {
                return innerArticle.Password;
            }
            set
            {
                innerArticle.Password = value;
            }
        }

        public override string Path
        {
            get
            {
                return innerArticle.Path;
            }
            set
            {
                innerArticle.Path = value;
            }
        }

        public override string PermaLink
        {
            get
            {
                if (!string.IsNullOrEmpty(innerArticle.PermaLink))
                {
                    if (innerArticle.PermaLink.StartsWith("http"))
                        return innerArticle.PermaLink;
                    else
                        return UrlResolver.ApplicationPath + "/publishing" + innerArticle.PermaLink;
                }
                return innerArticle.PermaLink;
            }
            set
            {
                innerArticle.PermaLink = value;
            }
        }

        public override string PingUrls
        {
            get
            {
                return innerArticle.PingUrls;
            }
            set
            {
                innerArticle.PingUrls = value;
            }
        }

        public override int Pos
        {
            get
            {
                return innerArticle.Pos;
            }
            set
            {
                innerArticle.Pos = value;
            }
        }

        public override DateTime Posted
        {
            get
            {
                return innerArticle.Posted;
            }
            set
            {
                innerArticle.Posted = value;
            }
        }

        public override double Ratings
        {
            get
            {
                return innerArticle.Ratings;
            }
            set
            {
                innerArticle.Ratings = value;
            }
        }

        public override int TotalReads
        {
            get
            {
                return innerArticle.TotalReads;
            }
            set
            {
                innerArticle.TotalReads = value;
            }
        }

        public override string SendTrackbackUrls
        {
            get
            {
                return innerArticle.SendTrackbackUrls;
            }
            set
            {
                innerArticle.SendTrackbackUrls = value;
            }
        }

        public override string Slug
        {
            get
            {
                return innerArticle.Slug;
            }
            set
            {
                innerArticle.Slug = value;
            }
        }

        public override string Summary
        {
            get
            {
                return innerArticle.Summary;
            }
            set
            {
                innerArticle.Summary = value;
            }
        }

        public override string Tags
        {
            get
            {
                return innerArticle.Tags;
            }
            set
            {
                innerArticle.Tags = value;
            }
        }

        public override string Title
        {
            get
            {
                return innerArticle.Title;
            }
            set
            {
                innerArticle.Title = value;
            }
        }

        public override int TotalComments
        {
            get
            {
                return innerArticle.TotalComments;
            }
            set
            {
                innerArticle.TotalComments = value;
            }
        }

        public override int TotalVotes
        {
            get
            {
                return innerArticle.TotalVotes;
            }
            set
            {
                innerArticle.TotalVotes = value;
            }
        }

        [ScriptIgnore]
        public override ICollection<Track> Tracks
        {
            get
            {
                return innerArticle.Tracks;
            }
            set
            {
                innerArticle.Tracks = value;
            }
        }

        [ScriptIgnore]
        public override ICollection<TranslatedCopy> TranslatedCopies
        {
            get
            {
                return innerArticle.TranslatedCopies;
            }
            set
            {
                innerArticle.TranslatedCopies = value;
            }
        }

        public override string UserName
        {
            get
            {
                return innerArticle.UserName;
            }
            set
            {
                innerArticle.UserName = value;
            }
        }

        public override int Version
        {
            get
            {
                return innerArticle.Version;
            }
            set
            {
                innerArticle.Version = value;
            }
        }

        [ScriptIgnore]
        public override ICollection<History> Versions
        {
            get
            {
                return innerArticle.Versions;
            }
            set
            {
                innerArticle.Versions = value;
            }
        }

        [ScriptIgnore]
        public override ICollection<Vote> Votes
        {
            get
            {
                return innerArticle.Votes;
            }
            set
            {
                innerArticle.Votes = value;
            }
        }

        #endregion

        #region IsOwner

        ///// <summary>
        ///// Determine the specified user is article owner.
        ///// </summary>
        ///// <param name="article">The Article object to extends.</param>
        ///// <param name="username">The user name.</param>
        ///// <returns></returns>
        //public bool IsOwner(string username)
        //{
        //    return UserName.Equals(username, StringComparison.OrdinalIgnoreCase);
        //}

        /// <summary>
        ///  Determine the current request user is article owner.
        /// </summary>
        /// <param name="article">The Article object to extends.</param>
        /// <returns></returns>
        public bool IsOwner(HttpContext context)
        {
            if (context.Request.IsAuthenticated && (context.User.Identity != null))
                return IsOwner(context.User.Identity.Name);
            return false;
        }

        public bool IsOwner(HttpContextBase context)
        {
            if (context.Request.IsAuthenticated && (context.User.Identity != null))
                return IsOwner(context.User.Identity.Name);
            return false;
        }

        #endregion

        public IEnumerable<string> GetSendTrackbackUrls()
        {
            var urls = new string[] { };
            if (!string.IsNullOrEmpty(SendTrackbackUrls))
                return SendTrackbackUrls.Split(',');
            return urls;
        }

        [ScriptIgnore]
        public string TrackbackUrl
        {
            get
            {
                return UrlResolver.ApplicationPath + "/openapi/trackback/" + ID.ToString();
            }
        }

        public IEnumerable<string> GetPingUrls()
        {
            var urls = new string[] { };
            if (!string.IsNullOrEmpty(PingUrls))
                return PingUrls.Split(',');
            return urls;
        }

        public TranslatedCopy GetTranslated(string lan)
        {
            return innerArticle.TranslatedCopies.FirstOrDefault(t => t.Language.Equals(lan, StringComparison.OrdinalIgnoreCase));
        }

        /// <summary>
        /// Gets the globalization content.
        /// </summary>
        /// <returns></returns>
        public GlobalizationContent GetGlobalizationContent()
        {
            return GetGlobalizationContent(System.Threading.Thread.CurrentThread.CurrentUICulture);
        }

        /// <summary>
        /// Gets the globalization content by specified CultureInfo.
        /// </summary>
        /// <param name="culture">The cultureinfo.</param>
        /// <returns></returns>
        public GlobalizationContent GetGlobalizationContent(CultureInfo culture)
        {
            if (_content == null)
                _content = new GlobalizationContent();
            else
            {
                if (_content.Culture.Equals(culture))
                    return _content;
            }

            if (culture.Name != this.Language)
            {
                // if (!this.TranslatedCopies.IsLoaded) this.TranslatedCopies.Load();
                var copy = this.GetTranslated(culture.Name);
                //this.TranslatedCopies.FirstOrDefault(t => t.Language == culture.Name);
                if (copy != null)
                {
                    _content.Culture = culture;
                    _content.Title = copy.Title;
                    _content.Summary = copy.Summary;
                    _content.Body = copy.Body;
                    return _content;
                }
            }

            _content.Title = this.Title;
            _content.Summary = this.Summary;
            _content.Body = this.Body;
            _content.Culture = culture;
            return _content;
        }

        /// <summary>
        /// Gets the article author object.
        /// </summary>
        [ScriptIgnore]
        public MembershipUser Author
        {
            get
            {
                return Membership.GetUser(UserName);
            }
        }

        public IEnumerable<CategoryWrapper> AllCategories()
        {
            var pubContext = DependencyResolver.Current.GetService<IPubContext>();
            var list = new List<CategoryWrapper>();
            var catArgs = !string.IsNullOrEmpty(Categories) ? Categories.Split(',') : new string[0];
            var root = Category.IsRoot ? Category : pubContext.Categories.Find(this.Category.GetRootPath());
            var cats = pubContext.Categories.Descendants(root.ID).Where(c => catArgs.Contains(c.Title));
            foreach (var cat in cats)
                list.Add(new CategoryWrapper(cat));
            list.Insert(0, new CategoryWrapper(Category));
            return list;
        }

        public string[] AllTaggs()
        {
            string[] tags = new string[0];
            if (!string.IsNullOrEmpty(Tags))
            {
                tags = Tags.Split(',');
            }
            return tags;
        }

        public bool IsVisible(HttpContextBase httpContext)
        {
            if (httpContext.Request.IsAuthenticated && IsOwner(httpContext))
                return true;

            if (httpContext.Request.IsAuthenticated && (httpContext.User.IsWebOwner() || httpContext.User.IsAdministrator()))
                return !IsPrivate;

            if (!IsOwner(httpContext))
            {
                if ((IsPrivate) || (!IsPublished))
                {
                    return false;
                }
            }

            return true;
        }
    }
}
